package conversation

import (
	"fmt"
	"strings"

	"gopkg.in/xmlpath.v2"

	"code.google.com/awwwe-browser/auralvm/param"
	"code.google.com/awwwe-browser/data"
	"code.google.com/awwwe-browser/scrub"
	"code.google.com/awwwe-browser/scrub/htmlsoup"
	"code.google.com/awwwe-browser/vois"
	"code.google.com/awwwe-browser/xpath"
)

// BuildSpeechLines builds article text for an article conversation.
func (this *Conversation) BuildSpeechLines(scrubber *scrub.Scrubber, tree *xmlpath.Node, onlyspeakat string) {
	var nodes []*htmlsoup.SoupNode
	var node *htmlsoup.SoupNode
	var speeches, lines []string
	var speech, line, fixedline string
	nodes = MatchXpathToTreeNodes(scrubber, tree, onlyspeakat)
	speeches = make([]string, 0, 5)
	for _, node = range nodes {
		speech = node.VoiceString()
		// todo translations
		speeches = append(speeches, speech)
	}
	// split on newlines
	speech = strings.Join(speeches, " ")
	lines = strings.Split(speech, data.VXMLLongPauseString)
	for _, line = range lines {
		fixedline = strings.Trim(line, data.WhiteSpaceString)
		if len(fixedline) > 0 {
			//fixedline = data.VXMLLongPause + fixedline
			this.Texts = append(this.Texts, fixedline)
		}
	}
}

// BuildSpeechArticleLinks builds links it finds in an article for a article links conversation.
func (this *Conversation) BuildSpeechArticleLinks(scrubber *scrub.Scrubber, tree *xmlpath.Node, onlyspeakat string, tabkey int, sourceobject, sourcemethod string, sourcestartindex int) {
	var textnodes []*xmlpath.Node
	var textnode *xmlpath.Node
	var filternodes []*htmlsoup.SoupNode
	var filternode *htmlsoup.SoupNode
	var link APIOption
	var vxml, href string
	var i, last int
	var tabkeystring string
	tabkeystring = fmt.Sprintf("%d", tabkey)
	// get the article text nodes
	textnodes = xpath.PathNodesString(onlyspeakat, tree)
	for _, textnode = range textnodes {
		// get the anchor nodes in the article text nodes
		filternodes = MatchXpathToTreeNodes(scrubber, textnode, ".//a")
		last = len(filternodes) - 1
		for i, filternode = range filternodes {
			// the link speech
			vxml = filternode.VoiceString()
			vxml = strings.Replace(vxml, data.VXMLLongPauseString, " ", -1)
			vxml = strings.Trim(vxml, data.WhiteSpaceString)
			if len(vxml) > 0 {
				_, _, href = filternode.GetAttribute("href")
				if len(href) > 0 {
					// the link url
					link = BuildAPIOption()
					link.VXMLs.Append(vxml)
					// the link calls
					link.CallYes.Package = param.Package
					link.CallYes.Object = "tab"
					link.CallYes.Method = "replace"
					link.CallYes.Arguments[param.ParamTabURL] = href
					link.CallYes.Arguments[param.ParamTabKey] = tabkeystring
					link.CallYes.Arguments[param.ParamSourceObject] = sourceobject
					link.CallYes.Arguments[param.ParamSourceMethod] = sourcemethod
					link.CallYes.Arguments[param.ParamSourceTabKey] = tabkeystring
					if i < last {
						link.CallYes.Arguments[param.ParamSourceOptionIndex] = fmt.Sprintf("%d", sourcestartindex)
						link.CallYes.Arguments[param.ParamSourceElementIndex] = fmt.Sprintf("%d", i+1)
					} else {
						link.CallYes.Arguments[param.ParamSourceOptionIndex] = fmt.Sprintf("%d", sourcestartindex+1)
						link.CallYes.Arguments[param.ParamSourceElementIndex] = fmt.Sprintf("%d", 0)
					}
					link.CallYesNew.Package = param.Package
					link.CallYesNew.Object = "tab"
					link.CallYesNew.Method = "opennew"
					link.CallYesNew.Arguments[param.ParamTabURL] = href
					link.CallYesNew.Arguments[param.ParamSourceObject] = sourceobject
					link.CallYesNew.Arguments[param.ParamSourceMethod] = sourcemethod
					link.CallYesNew.Arguments[param.ParamSourceTabKey] = tabkeystring
					if i < last {
						link.CallYesNew.Arguments[param.ParamSourceOptionIndex] = fmt.Sprintf("%d", sourcestartindex)
						link.CallYesNew.Arguments[param.ParamSourceElementIndex] = fmt.Sprintf("%d", i+1)
					} else {
						link.CallYesNew.Arguments[param.ParamSourceOptionIndex] = fmt.Sprintf("%d", sourcestartindex+1)
						link.CallYesNew.Arguments[param.ParamSourceElementIndex] = fmt.Sprintf("%d", 0)
					}
					// add the link
					this.Options = append(this.Options, link)
				}
			}
		}
	}
}

// BuildSpeechLinks builds links for a navigation conversation.
func (this *Conversation) BuildSpeechLinks(scrubber *scrub.Scrubber, tree *xmlpath.Node, onlyspeakat string, tabkey int, sourceobject, sourcemethod string, sourcestartindex int) {
	var filternodes []*htmlsoup.SoupNode
	var filternode *htmlsoup.SoupNode
	var link APIOption
	var vxml, href string
	var i, last int
	var tabkeystring string
	var children []*htmlsoup.SoupNode
	var child *htmlsoup.SoupNode
	filternodes = MatchXpathToTreeNodes(scrubber, tree, onlyspeakat)
	tabkeystring = fmt.Sprintf("%d", tabkey)
	last = len(filternodes) - 1
	for i, filternode = range filternodes {
		// the link speech
		vxml = filternode.VoiceString()
		vxml = strings.Replace(vxml, data.VXMLLongPauseString, " ", -1)
		vxml = strings.Trim(vxml, data.WhiteSpaceString)
		if len(vxml) > 0 {
			// get the href from the anchor node
			href = data.EmptyString
			if filternode.Name() == "a" {
				_, _, href = filternode.GetAttribute("href")
			} else {
				// get the href from an "a" node inside filternode
				children = filternode.Children()
				for _, child = range children {
					if child.Name() == "a" {
						_, _, href = child.GetAttribute("href")
						if len(href) > 0 {
							break
						}
					}
				}
			}
			if len(href) > 0 {
				// the link url
				link = BuildAPIOption()
				link.VXMLs.Append(vxml)
				// the link calls
				link.CallYes.Package = param.Package
				link.CallYes.Object = "tab"
				link.CallYes.Method = "replace"
				link.CallYes.Arguments[param.ParamTabURL] = href
				link.CallYes.Arguments[param.ParamTabKey] = tabkeystring
				link.CallYes.Arguments[param.ParamSourceObject] = sourceobject
				link.CallYes.Arguments[param.ParamSourceMethod] = sourcemethod
				link.CallYes.Arguments[param.ParamSourceTabKey] = tabkeystring
				if i < last {
					link.CallYes.Arguments[param.ParamSourceOptionIndex] = fmt.Sprintf("%d", sourcestartindex)
					link.CallYes.Arguments[param.ParamSourceElementIndex] = fmt.Sprintf("%d", i+1)
				} else {
					link.CallYes.Arguments[param.ParamSourceOptionIndex] = fmt.Sprintf("%d", sourcestartindex+1)
					link.CallYes.Arguments[param.ParamSourceElementIndex] = fmt.Sprintf("%d", 0)
				}
				link.CallYesNew.Package = param.Package
				link.CallYesNew.Object = "tab"
				link.CallYesNew.Method = "opennew"
				link.CallYesNew.Arguments[param.ParamTabURL] = href
				link.CallYesNew.Arguments[param.ParamSourceObject] = sourceobject
				link.CallYesNew.Arguments[param.ParamSourceMethod] = sourcemethod
				link.CallYesNew.Arguments[param.ParamSourceTabKey] = tabkeystring
				if i < last {
					link.CallYesNew.Arguments[param.ParamSourceOptionIndex] = fmt.Sprintf("%d", sourcestartindex)
					link.CallYesNew.Arguments[param.ParamSourceElementIndex] = fmt.Sprintf("%d", i+1)
				} else {
					link.CallYesNew.Arguments[param.ParamSourceOptionIndex] = fmt.Sprintf("%d", sourcestartindex+1)
					link.CallYesNew.Arguments[param.ParamSourceElementIndex] = fmt.Sprintf("%d", 0)
				}
				// add the link
				this.Options = append(this.Options, link)
			}
		}
	}
}

// BuildAtomSpeechLinks builds links for a atom feed navigation article.
func (this *Conversation) BuildAtomSpeechLinks(sitevdata *vois.VOISData, tree *xmlpath.Node, onlyspeakat string, tabkey int, sourceobject, sourcemethod string, sourcestartindex int) {
	var xnodes, chnodes, lnodes []*xmlpath.Node
	var xnode *xmlpath.Node
	var link APIOption
	var i, last, length int
	var tabkeystring string
	var id, vxml, href string
	var captures [][]string
	var captured []string
	captures = make([][]string, 0, 5)
	// xnodes are /feed/entry
	xnodes = xpath.PathNodesString(onlyspeakat, tree)
	for _, xnode = range xnodes {
		// /feed/entry/id
		chnodes = xpath.PathNodesString("./id", xnode)
		if len(chnodes) > 0 {
			id = chnodes[0].String()
			// /feed/entry/link
			chnodes = xpath.PathNodesString(`./link[@rel="alternate" and @type="text/html"]`, xnode)
			if len(chnodes) > 0 {
				lnodes = xpath.PathNodesString("@title", chnodes[0])
				if len(lnodes) > 0 {
					vxml = lnodes[0].String()
					vxml = htmlsoup.MakeSpeakable(vxml)
					vxml = sitevdata.Translate(vxml)
					lnodes = xpath.PathNodesString("@href", chnodes[0])
					if len(lnodes) > 0 {
						href = lnodes[0].String()
						// add the link data
						captures = append(captures, []string{id, vxml, href})
					}
				}
			}
		}
	}
	if len(captures) > 0 {
		tabkeystring = fmt.Sprintf("%d", tabkey)
		length = len(captures)
		last = length - 1
		for i = 0; i < length; i++ {
			captured = captures[i]
			id = captured[0]
			vxml = captured[1]
			href = captured[2]
			// the link speech
			vxml = strings.Trim(vxml, data.WhiteSpaceString)
			vxml = htmlsoup.MakeSpeakable(vxml)
			vxml = sitevdata.Translate(vxml)
			if len(vxml) > 0 {
				// the link url
				link = BuildAPIOption()
				link.VXMLs.Append(vxml)
				// the link calls
				link.CallYes.Package = param.Package
				link.CallYes.Object = "tab"
				link.CallYes.Method = "opennew"
				link.CallYes.Arguments[param.ParamTabURL] = href
				link.CallYes.Arguments[param.ParamFeedItemKey] = id
				link.CallYes.Arguments[param.ParamSourceObject] = sourceobject
				link.CallYes.Arguments[param.ParamSourceMethod] = sourcemethod
				link.CallYes.Arguments[param.ParamSourceTabKey] = tabkeystring
				if i < last {
					link.CallYes.Arguments[param.ParamSourceOptionIndex] = fmt.Sprintf("%d", sourcestartindex)
					link.CallYes.Arguments[param.ParamSourceElementIndex] = fmt.Sprintf("%d", i+1)
				} else {
					link.CallYes.Arguments[param.ParamSourceOptionIndex] = fmt.Sprintf("%d", sourcestartindex+1)
					link.CallYes.Arguments[param.ParamSourceElementIndex] = fmt.Sprintf("%d", 0)
				}
				// add the link
				this.Options = append(this.Options, link)
			}
		}
	}
}

// BuildRSSSpeechLinks builds links for an rss feed navigation article.
func (this *Conversation) BuildRSSSpeechLinks(sitevdata *vois.VOISData, tree *xmlpath.Node, onlyspeakat string, tabkey int, sourceobject, sourcemethod string, sourcestartindex int) {
	var xnodes, chnodes []*xmlpath.Node
	var xnode *xmlpath.Node
	var id, vxml, href string
	var tabkeystring string
	var captures [][]string
	var captured []string
	var i, last, length int
	var link APIOption
	captures = make([][]string, 0, 5)
	// xnodes are /feed/entry
	xnodes = xpath.PathNodesString(onlyspeakat, tree)
	for _, xnode = range xnodes {
		// /feed/entry/id
		chnodes = xpath.PathNodesString("./guid", xnode)
		if len(chnodes) > 0 {
			id = chnodes[0].String()
			chnodes = xpath.PathNodesString("./title", xnode)
			if len(chnodes) > 0 {
				vxml = chnodes[0].String()
				chnodes = xpath.PathNodesString("./link", xnode)
				if len(chnodes) > 0 {
					href = chnodes[0].String()
					// add the link data
					captures = append(captures, []string{id, vxml, href})
				}
			}
		}
	}
	if len(captures) > 0 {
		tabkeystring = fmt.Sprintf("%d", tabkey)
		length = len(captures)
		last = length - 1
		for i = 0; i < length; i++ {
			captured = captures[i]
			id = captured[0]
			vxml = captured[1]
			href = captured[2]
			// the link speech
			vxml = strings.Trim(vxml, data.WhiteSpaceString)
			vxml = htmlsoup.MakeSpeakable(vxml)
			if len(vxml) > 0 {
				// the link url
				link = BuildAPIOption()
				link.VXMLs.Append(vxml)
				// the link calls
				link.CallYes.Package = param.Package
				link.CallYes.Object = "tab"
				link.CallYes.Method = "opennew"
				link.CallYes.Arguments[param.ParamTabURL] = href
				link.CallYes.Arguments[param.ParamFeedItemKey] = id
				link.CallYes.Arguments[param.ParamSourceObject] = sourceobject
				link.CallYes.Arguments[param.ParamSourceMethod] = sourcemethod
				link.CallYes.Arguments[param.ParamSourceTabKey] = tabkeystring
				if i < last {
					link.CallYes.Arguments[param.ParamSourceOptionIndex] = fmt.Sprintf("%d", sourcestartindex)
					link.CallYes.Arguments[param.ParamSourceElementIndex] = fmt.Sprintf("%d", i+1)
				} else {
					link.CallYes.Arguments[param.ParamSourceOptionIndex] = fmt.Sprintf("%d", sourcestartindex+1)
					link.CallYes.Arguments[param.ParamSourceElementIndex] = fmt.Sprintf("%d", 0)
				}
				// add the link
				this.Options = append(this.Options, link)
			}
		}
	}
}
